ABC032 D - ナップサック問題
https://atcoder.jp/contests/abc032/tasks/abc032_d
提出
code: python
n, w = map(int, input().split())
vw = list(map(int, input().split())) for _ in range(n)
dp = [0 * (w + 1) for i in range(n + 1)]
for i in range(n):
for j in range(w + 1):
# ナップサックのキャパ(j)が品物のi番目の品物の重さ(vwi1)より小さかったら
if (j < vwi1):
# 入らないのでそのまま
dpi + 1j = dpij
else:
# i番目の品物が入る前の価値(dpi[j - wi])にi番目の品物の価値(vi)を足した場合と、
# i番目の品物を入れなかった場合を比較
dpi + 1j = max(dpij, dpi[j - vwi1] + vwi0)
print(dpnw)
解答
code: python
from bisect import *
from collections import defaultdict
n, w = map(int, input().split())
vw = list(map(int, input().split())) for _ in range(n)
vl, wl = [], []
for vi, wi in vw:
vl.append(vi)
wl.append(wi)
# print(vl, wl)
# 15, 10, 6 9, 6, 4
# 半分全列挙
def solve1():
vl1, vl2 = vl:n//2, vln//2:
wl1, wl2 = wl:n//2, wln//2:
d1 = defaultdict(int)
for bit in range(2 ** len(vl1)):
tmpv = 0
tmpw = 0
for i in range(len(vl1)):
if (bit >> i) & 1:
tmpv += vl1i
tmpw += wl1i
d1tmpw = max(d1tmpw, tmpv)
# print(d1)
# defaultdict(<class 'int'>, {0: 0, 9: 15})
d2 = defaultdict(int)
for bit in range(2 ** len(vl2)):
tmpv = 0
tmpw = 0
for i in range(len(vl2)):
if (bit >> i) & 1:
tmpv += vl2i
tmpw += wl2i
d2tmpw = max(d2tmpw, tmpv)
# print(d2)
# defaultdict(<class 'int'>, {0: 0, 6: 10, 4: 6, 10: 16})
# d2 において、各重量で達成できる最大の価値が連続して増加するように
d2w = sorted(d2.keys())
for i in range(len(d2w) - 1):
k1, k2 = d2wi, d2wi+1
if d2k2 < d2k1:
d2k2 = d2k1
# print(d2)
# defaultdict(<class 'int'>, {0: 0, 6: 10, 4: 6, 10: 16})
res = 0
for w1 in d1:
if w1 > w:
continue
# d2 の keys のうち、残りの重量制限を超えない最大のキーの位置
j = bisect_right(d2w, w - w1)
w2 = d2wj-1
res = max(res, d1w1 + d2w2)
return res
# wを横軸にしたDP
def solve2():
# dpi := 重さ i の時の価値の最大値
dp = 0 * (w + 1)
for i in range(n):
vi, wi = vli, wli
for j in range(w, wi - 1, -1):
dpj = max(dpj, dpj-wi + vi)
return dpw
# vを横軸にしたDP
def solve3():
maxv = n * 1000
# dpi := 価値 i の時の重さの最小値
dp = float('inf') * (maxv + 1)
dp0 = 0
for i in range(n):
vi, wi = vli, wli
for j in range(maxv, vi-1, -1):
dpj = min(dpj, dpj-vi + wi)
res = 0
for i in range(maxv + 1):
if dpi <= w:
res = i
return res
if n <= 30:
print(solve1())
elif max(wl) <= 1000:
print(solve2())
else:
print(solve3())
テーマ
#dp
蟻本 2-3 01ナップサック問題その2
メモ
提出 #28077508
https://img.atcoder.jp/abc032/editorial.pdf
Pythonで半分全列挙を実装してみる-ABC184
提出
code: python
n, w = map(int, input().split())
vw = list(map(int, input().split())) for _ in range(n)
# print(vw)
# 15, 9], 10, 6, [6, 4
# 全探索: O(pow(2, n))
# dpij := アイテム i 個, 重さ j までの価値の最大値
dp = [0 * (w+1) for _ in range(n+1)]
for i in range(1, n+1):
for j in range(w+1):
if j - vwi1 >= 0:
dpij = max(dpij, dpi-1j)